home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 1.toast / pc / tool chest / development kits / c++ related / thooks / hooks.cp < prev    next >
Encoding:
Text File  |  1990-09-14  |  4.3 KB  |  184 lines

  1. /*
  2.     File:        Hooks.cp
  3.  
  4.     Contains:    Hooking into the Mac OS by intercepting traps
  5.  
  6.     A "hook" consists of a short machine-language sequence that calls
  7.     our trap monitoring routine, and then passes control onto the ROM routine
  8.     This sequence must be placed in the system heap so that it is guaranteed
  9.     to be close enough to the trap dispatch table.
  10.     
  11.     Between the time that we first install this hook and the time that we
  12.     are ready to remove it, the application may have installed a hook of its
  13.     own!  If it has, we can't just remove our hook by restoring the old
  14.     trap handler.  Instead we disable the hook by having it jump directly
  15.     to the original routine.
  16.  
  17.     Written by:    Jack Palevich, [Original idea and C implementation by Jay Fenton]
  18.  
  19.     Copyright:    © 1989 by Apple Computer, Inc., all rights reserved.
  20.  
  21.     Change History:
  22.  
  23.         10/15/89    JHP        objectified today
  24.  
  25.     To Do:
  26. */
  27.  
  28. #ifndef __OSUTILS__
  29. #include <OSUtils.h>
  30. #endif
  31. #ifndef __MEMORY__
  32. #include <Memory.h>
  33. #endif
  34. #ifndef __SYSEQU__
  35. #include <SysEqu.h>
  36. #endif
  37.  
  38. #ifndef __HOOKS__
  39. #include "Hooks.h"
  40. #endif
  41.  
  42.     /* At the point we do the move.l sp,-(sp) this is the state of the stack
  43.  
  44.        offset    size    what's there
  45.        ======    ====    =======================
  46.        0        2        trap number
  47.        2        4        d0
  48.        6        4        d1
  49.        10        4        d2
  50.        14        4        d3
  51.        18        4        d4
  52.        22        4        d5
  53.        26        4        d6
  54.        30        4        d7
  55.        34        4        a0
  56.        38        4        a1
  57.        42        4        a2
  58.        46        4        a3
  59.        50        4        a4
  60.        54        4        a5
  61.        58        4        return address
  62.        62        ?        last argument to trap
  63.        62+?        ?        second to last argument to trap
  64.      */
  65.  
  66. struct hookentry {
  67.     long            movemON;    // movem.l    d0-d7/a0-a5,-(sp)
  68.  
  69.     short            moveiw;        // movei.w    #,-sp
  70.     short            tNumber;
  71.  
  72.     short            pushsp;        // move.l    sp,-(sp)
  73.  
  74.     short            moveil;        // movei.l    #,-sp
  75.     void*            userRefNum;
  76.  
  77.     short            JSR;
  78.     pascal void (*subroutine)(short, THookStackFrame*, void*);
  79.  
  80.     long            movemOFF;    // movem.l    (sp)+,d0-d7/a0-a5
  81.  
  82.     short            JMP;        // jmp.l    #
  83.     long            OldTrapAddr;
  84. };
  85.  
  86. struct patch {
  87.     short    JMP;
  88.     long    OldTrapAddr;
  89.     };
  90. typedef patch *patchptr;
  91.  
  92. THooks::THooks(short numTraps, const short* trapList,
  93.     pascal void (*trapHandler)(short, THookStackFrame*, void* userRefNum), void* userRefNum)
  94.     {
  95.     // Allocate fHooks in the system heap
  96.     
  97.     fHooks =  (hookentry*) NewPtrSys( sizeof( hookentry) * numTraps);
  98.     
  99.     if ( ! fHooks ) return;
  100.  
  101.     fNumHooks = numTraps;
  102.     
  103.     
  104.     for ( short i = 0; i < numTraps; i++ )
  105.         {
  106.         hookentry* hooker = & fHooks[i];
  107.         short whatTrap = trapList[i];
  108.         TrapType trapType;
  109.         short trapNum;
  110.         TrapToTypeAndNum(whatTrap, trapType, trapNum);
  111.         hooker->movemON = 0x48E7FFFc;        // movem.l    d0-d7/a0-a5,-(sp)
  112.         hooker->moveiw = 0x3F3C;            // movei.w    #,-(sp)
  113.         hooker->tNumber = whatTrap;         // a code number
  114.         hooker->pushsp = 0x2F0F;            // move.l sp,-(sp)
  115.         hooker->moveil = 0x2F3C;            // movei.l    #,-(sp)
  116.         hooker->userRefNum = userRefNum;
  117.         hooker->JSR = 0x4EB9;                // JSR abs.l
  118.         hooker->subroutine = trapHandler;
  119.         hooker->movemOFF = 0x4CDF3FFF;        // movem.l    (sp)+,d0-d7/a0-a5
  120.         hooker->JMP = 0x4EF9;                // JMP abs.l
  121.         hooker->OldTrapAddr = NGetTrapAddress(trapNum, trapType);
  122.         NSetTrapAddress((long) hooker, trapNum, trapType);
  123.         } // for i
  124.     }
  125.  
  126.  
  127. THooks::~THooks()
  128.     {
  129.     if ( ! fHooks ) return;    // Never allocated
  130.  
  131.     register short i;
  132.     // first check to verify that none of the traps have been 
  133.     // overriden by someone else:
  134.     
  135.     Boolean clean = true;
  136.     
  137.     for (i = 0; i < fNumHooks; i++)
  138.         {
  139.          TrapType trapType;
  140.         short trapNum;
  141.         TrapToTypeAndNum(fHooks[i].tNumber, trapType, trapNum);
  142.         if ( ((long) NGetTrapAddress(trapNum, trapType) ) !=
  143.                 fHooks[i].OldTrapAddr)
  144.             {
  145.             clean = false;
  146.             break;
  147.             }
  148.         }
  149.  
  150.     if ( clean )
  151.         {
  152.         // Yay!  Nobody's patched after us, so we can unpatch ourselves
  153.     
  154.         for (i = 0; i < fNumHooks; i++)
  155.             {
  156.             TrapType trapType;
  157.             short trapNum;
  158.             TrapToTypeAndNum(fHooks[i].tNumber, trapType, trapNum);
  159.             NSetTrapAddress(fHooks[i].OldTrapAddr, trapNum, trapType);
  160.             }
  161.         // and we can delete our hook array
  162.  
  163.         THz oldZone = (*(THz*) TheZone);
  164.         SetZone((*(THz*) SysZone));        
  165.         DisposPtr((Ptr) fHooks);
  166.         SetZone(oldZone);
  167.  
  168.         fHooks = 0;
  169.         }
  170.     else
  171.         {
  172.         // we can not completely extract our patch area, so we leave it in place, but we
  173.         // short-circuit the patch
  174.         
  175.         for (i = 0; i < fNumHooks; i++)
  176.             { /* point at our jump instruction leading out */
  177.             hookentry* h = & fHooks[i];
  178.             patchptr thispatch = (patchptr) h;
  179.             thispatch->JMP = 0x4EF9;
  180.             thispatch->OldTrapAddr = h->OldTrapAddr;
  181.             }
  182.         }
  183.     }
  184.